GdkWindow: Track all native windows of native windows
authorAlexander Larsson <alexl@redhat.com>
Wed, 15 May 2013 08:23:14 +0000 (10:23 +0200)
committerAlexander Larsson <alexl@redhat.com>
Wed, 15 May 2013 09:08:35 +0000 (11:08 +0200)
We keep a list of all native children of a native window. This means
we don't have to recurse over the entire hierarchy to find any
native children.

gdk/gdkinternals.h
gdk/gdkwindow.c
gdk/win32/gdkwindow-win32.c
gdk/x11/gdkwindow-x11.c

index 87d3fbc35677ece4c8f913ad8b74452a48bda838..3f2d1a4b95e9751cd30ee4fb9e0ad7c3277f0612 100644 (file)
@@ -189,6 +189,7 @@ struct _GdkWindow
 
   GList *filters;
   GList *children;
+  GList *native_children;
 
   cairo_pattern_t *background;
 
index f4f144013c517a32d7860a3b61c220994b9ee20f..2c9a2a1ee12aaba537385c45faaba7c85929f802 100644 (file)
@@ -1375,6 +1375,9 @@ gdk_window_new (GdkWindow     *parent,
       _gdk_display_create_window_impl (display, window, real_parent, screen, event_mask, attributes, attributes_mask);
       window->impl_window = window;
 
+      if (parent)
+        parent->impl_window->native_children = g_list_prepend (parent->impl_window->native_children, window);
+
       /* This will put the native window topmost in the native parent, which may
        * be wrong wrt other native windows in the non-native hierarchy, so restack */
       if (!_gdk_window_has_impl (real_parent))
@@ -1444,6 +1447,14 @@ change_impl (GdkWindow *private,
 
       if (child->impl == old_impl)
        change_impl (child, impl_window, new);
+      else
+        {
+          /* The child is a native, update native_children */
+          old_impl_window->native_children =
+            g_list_remove (old_impl_window->native_children, child);
+          impl_window->native_children =
+            g_list_prepend (impl_window->native_children, child);
+        }
     }
 }
 
@@ -1570,7 +1581,13 @@ gdk_window_reparent (GdkWindow *window,
     }
 
   if (old_parent)
-    old_parent->children = g_list_remove (old_parent->children, window);
+    {
+      old_parent->children = g_list_remove (old_parent->children, window);
+
+      if (gdk_window_has_impl (window))
+        old_parent->impl_window->native_children =
+          g_list_remove (old_parent->impl_window->native_children, window);
+    }
 
   window->parent = new_parent;
   window->x = x;
@@ -1578,6 +1595,9 @@ gdk_window_reparent (GdkWindow *window,
 
   new_parent->children = g_list_prepend (new_parent->children, window);
 
+  if (gdk_window_has_impl (window))
+    new_parent->impl_window->native_children = g_list_prepend (new_parent->impl_window->native_children, window);
+
   /* Switch the window type as appropriate */
 
   switch (GDK_WINDOW_TYPE (new_parent))
@@ -1686,7 +1706,7 @@ gdk_window_ensure_native (GdkWindow *window)
   GdkWindowImpl *new_impl, *old_impl;
   GdkDisplay *display;
   GdkScreen *screen;
-  GdkWindow *above;
+  GdkWindow *above, *parent;
   GList listhead;
   GdkWindowImplClass *impl_class;
 
@@ -1711,15 +1731,20 @@ gdk_window_ensure_native (GdkWindow *window)
 
   screen = gdk_window_get_screen (window);
   display = gdk_screen_get_display (screen);
+  parent = window->parent;
 
   old_impl = window->impl;
   _gdk_display_create_window_impl (display,
-                                   window, window->parent,
+                                   window, parent,
                                    screen,
                                    get_native_event_mask (window),
                                    NULL, 0);
   new_impl = window->impl;
 
+  if (parent)
+    parent->impl_window->native_children =
+      g_list_prepend (parent->impl_window->native_children, window);
+
   window->impl = old_impl;
   change_impl (window, window, new_impl);
 
@@ -1729,7 +1754,7 @@ gdk_window_ensure_native (GdkWindow *window)
    * native parent, which may be wrong wrt the position of the previous
    * non-native window wrt to the other non-native children, so correct this.
    */
-  above = find_native_sibling_above (window->parent, window);
+  above = find_native_sibling_above (parent, window);
   if (above)
     {
       listhead.data = window;
@@ -1925,6 +1950,10 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
              if (window->parent->children)
                window->parent->children = g_list_remove (window->parent->children, window);
 
+              if (gdk_window_has_impl (window))
+                window->parent->impl_window->native_children =
+                  g_list_remove (window->parent->impl_window->native_children, window);
+
              if (!recursing &&
                  GDK_WINDOW_IS_MAPPED (window))
                {
@@ -1967,6 +1996,9 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
                }
 
              g_list_free (children);
+
+              if (gdk_window_has_impl (window))
+                g_assert (window->native_children == NULL);
            }
 
          _gdk_window_clear_update_area (window);
index 4ec80c1eea113a74b25844ce3857a2ace08bb171..29714b52648c20224e7b9413a5c1fbace8f06825 100644 (file)
@@ -714,6 +714,8 @@ gdk_win32_window_foreign_new_for_display (GdkDisplay      *display,
     window->parent = _gdk_root;
   
   window->parent->children = g_list_prepend (window->parent->children, window);
+  window->parent->impl_window->native_children =
+    g_list_prepend (window->parent->impl_window->native_children, window);
 
   GetClientRect ((HWND) anid, &rect);
   point.x = rect.left;
index 6f3a8ebd4b3e0495c11385bc1ba41cb512e4e97f..1f1dbf1161de6ed6eb6014aac7fe9c3af2492351 100644 (file)
@@ -1226,6 +1226,8 @@ gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
     win->parent = gdk_screen_get_root_window (screen);
 
   win->parent->children = g_list_prepend (win->parent->children, win);
+  win->parent->impl_window->native_children =
+    g_list_prepend (win->parent->impl_window->native_children, win);
 
   impl->xid = window;